﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Macad.Core.Topology;
using Macad.Core;
using Macad.Interaction;
using Macad.Occt; 
using Macad.Common;
using Macad.Interaction.Visual;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using static Macad.Interaction.ToggleSubshapesAction;
using System.Windows.Forms.VisualStyles;
using Macad.Core.Shapes;
using SpCad.Tools;
using System.Windows.Shapes;

namespace SpCad.Utils
{
    public class SelectAction : ToolAction
    {
        public bool SelectOnMouseDown { get; set; }

        //--------------------------------------------------------------------------------------------------

        public class EventArgs
        {
            public TopoDS_Shape SelectedSubshape { get; init; }
            public InteractiveEntity SelectedEntity { get; init; }
            public SubshapeTypes SelectedSubshapeType { get; init; }
            public AIS_InteractiveObject SelectedAisObject { get; init; }
            public MouseEventData MouseEventData { get; init; }
            public bool IsDo { get; set; }
        }

        public delegate void EventHandler(SelectAction sender, EventArgs args);
        public event EventHandler Preview;
        public event EventHandler Finished;

        //--------------------------------------------------------------------------------------------------

        SelectionContext _SelectionContext;
        readonly InteractiveEntity _SourceEntity;
        readonly SubshapeTypes _SubshapeTypes;
        readonly List<TopoDS_Shape> _Shapes;
        Trsf? _LocalTransformation; 
        readonly ISelectionFilter _SelectionFilter;
        readonly Color _SubshapeColor;
        readonly List<Subshape> _Subshapes = new();
        Prs3d_Drawer _TopmostHighlightDrawer;
        //--------------------------------------------------------------------------------------------------

        public SelectAction(SubshapeTypes subshapeTypes, InteractiveEntity sourceEntity = null, ISelectionFilter selectionFilter = null) : base()
        {
            _SubshapeTypes = subshapeTypes;
            _SourceEntity = sourceEntity;
            _SelectionFilter = selectionFilter;
             
        }

        //--------------------------------------------------------------------------------------------------

        public SelectAction(SubshapeTypes subshapeTypes, IEnumerable<TopoDS_Shape> shapes, InteractiveEntity sourceEntity = null, Color? color = null) : base()
        {
            _SubshapeTypes = subshapeTypes;
            _Shapes = shapes.ToList(); 
            //_SubshapeColor = color ?? Colors.FilteredSubshapes;
            _SourceEntity = sourceEntity;
        }
        public void AddSubshape(TopoDS_Shape shape, Trsf trsf, bool isSelected)
        {
            //.GetTransformation()
         
            var subshape = _Subshapes.FirstOrDefault(c => c.Shape.IsPartner(shape));
            if (subshape != null)
            {
                subshape.IsSelected = !subshape.IsSelected;
                var cl = subshape.IsSelected ? Colors.FilteredSubshapesHot : Colors.FilteredSubshapes;
                subshape.AisShape.SetColor((subshape.IsSelected ? Colors.FilteredSubshapesHot : Colors.FilteredSubshapes).ToQuantityColor());
                return;
            }
            subshape = new Subshape()
            {
                Shape = shape,
                IsSelected = isSelected,
                AisShape = new AIS_Shape(shape),
                id=Guid.NewGuid(),
            };
            //Debug.WriteLine(string.Format("Added component to sum: {0}", Subshapes.Count));
            subshape.AisShape.SetLocalTransformation(trsf); 
            subshape.AisShape.SetColor((isSelected ? Colors.FilteredSubshapesHot : Colors.FilteredSubshapes).ToQuantityColor());
            subshape.AisShape.Attributes().WireAspect().SetWidth(AppConfig.Get.SelctEdgeWidth);
            //subshape.AisShape.SetMaterial(new Graphic3d_MaterialAspect(Graphic3d_NameOfMaterial.Plastified));
            subshape.AisShape.SetPolygonOffsets(0, 1.01f, 1.0f);
            subshape.AisShape.SetZLayer(-2 /* Top */);
           
           if(shape is TopoDS_Vertex)
            {//Aspect_TypeOfMarker.Aspect_TOM_O
                Prs3d_PointAspect pointAspect = new Prs3d_PointAspect(Aspect_TypeOfMarker.O_POINT, Colors.ActionRed.ToQuantityColor(), 12.0);
                subshape.AisShape.Attributes().SetPointAspect(pointAspect);  
               
                subshape.AisShape.SetAspect(pointAspect);
                subshape.AisShape.Attributes().SetPointAspect(pointAspect); 

            }
           
            subshape.AisShape.Attributes().VectorAspect()?.SetWidth(20);
            subshape.AisShape.Attributes().VectorAspect()?.SetColor(Colors.ActionRed.ToQuantityColor());
            if (_TopmostHighlightDrawer == null)
            {
                _TopmostHighlightDrawer = new Prs3d_Drawer();
                _TopmostHighlightDrawer.SetLink(WorkspaceController.Workspace.AisContext.HighlightStyle(Prs3d_TypeOfHighlight.Dynamic));
                _TopmostHighlightDrawer.SetZLayer(-2 /* Top */);
                _TopmostHighlightDrawer.SetDisplayMode(1);
                _TopmostHighlightDrawer.SetColor(Colors.Highlight.ToQuantityColor());
            }
            //subshape.AisShape.SetDynamicHilightAttributes(_TopmostHighlightDrawer);

            WorkspaceController.Workspace.AisContext.Display(subshape.AisShape, false);

            WorkspaceController.Workspace.AisContext.Activate(subshape.AisShape, 0, false);
            WorkspaceController.Workspace.AisContext.SetSelectionSensitivity(subshape.AisShape, 0, 10);
 
            _Subshapes.Add(subshape);
 
        }
     
        //--------------------------------------------------------------------------------------------------

        protected override bool OnStart()
        {
            if (_Shapes==null)
            {
                _SelectionContext = OpenSelectionContext();


                _SelectionContext.Include(_SourceEntity);
                Body @body=(Body)_SourceEntity;
 
                
            }
            else if (_Shapes != null)
            {
                _SelectionContext = OpenSelectionContext();
                _SelectionContext.Include(_SourceEntity);
                Body mybody = (Body)_SourceEntity;
                var bodyBrep = mybody.GetBRep();

                var edges = bodyBrep.Edges(true);
                edges.ForEach(edge =>
                {
                    AddSubshape(edge, mybody.GetTransformation(), false);
                });
                foreach (var shape in _Shapes)
                {
                    AddSubshape(shape, mybody.GetTransformation(), true);
                    var aisShape = new AIS_Shape(shape);
                  
                  
                    _Subshapes.Add(new Subshape { IsSelected=true, AisShape = aisShape, Shape = shape });
                }
            }
            else
            {
                _SelectionContext = OpenSelectionContext(SelectionContext.Options.IncludeAll);
            }
            
            _SelectionContext.SetSubshapeSelection(_SubshapeTypes);
            _SelectionContext.SetSelectionFilter(_SelectionFilter);

            return true;
        }

        //--------------------------------------------------------------------------------------------------

        protected override void Cleanup()
        { 
            Preview = null;
            Finished = null;
            foreach (var subshape in _Subshapes)
            {
                if (subshape.AisShape != null)
                {
                    WorkspaceController.Workspace.AisContext.Remove(subshape.AisShape, false);
                }
            }
            _Subshapes.Clear();
            base.Cleanup();
        }

        //--------------------------------------------------------------------------------------------------

        public void UpdateShapes(IEnumerable<TopoDS_Shape> shapes, Trsf? localTransformation = null)
        {
            if (localTransformation != null)
            {
                _LocalTransformation = localTransformation;
            }

            int index = 0;
            foreach (var shape in shapes)
            {
                if (index > _Shapes.Count)
                    return;

                _Subshapes[index].Shape= shape; 
                _Subshapes[index].AisShape.SetShape(shape);
                if (_LocalTransformation != null)
                {
                    _Subshapes[index].AisShape.SetLocalTransformation(_LocalTransformation.Value);
                }
                WorkspaceController.Workspace.AisContext.Redisplay(_Subshapes[index].AisShape, false, true);
                index++;
            }
        }

        //--------------------------------------------------------------------------------------------------

        EventArgs ProcessMouseInput(MouseEventData data)
        {
            InteractiveEntity selectedEntity = data.DetectedEntities.FirstOrDefault();
            AIS_InteractiveObject selectedAisObject = data.DetectedAisInteractives.FirstOrDefault();
            TopoDS_Shape selectedSubshape = null;
            SubshapeTypes selectedSubshapeType = SubshapeTypes.None;

            if (data.DetectedShapes.Count > 0)
            {
                var detectedShape = data.DetectedShapes[0];

                if (_SubshapeTypes.HasFlag(SubshapeTypes.Vertex) && detectedShape.ShapeType() == TopAbs_ShapeEnum.VERTEX)
                {
                    selectedSubshape = detectedShape;
                    selectedSubshapeType = SubshapeTypes.Vertex;
                }
                else if (_SubshapeTypes.HasFlag(SubshapeTypes.Edge) && detectedShape.ShapeType() == TopAbs_ShapeEnum.EDGE)
                {
                    selectedSubshape = detectedShape;
                    selectedSubshapeType = SubshapeTypes.Edge;
                }
                else if (_SubshapeTypes.HasFlag(SubshapeTypes.Wire)  && detectedShape.ShapeType() == TopAbs_ShapeEnum.WIRE)
                {
                    selectedSubshape = detectedShape;
                    selectedSubshapeType = SubshapeTypes.Wire;
                }
                else if (_SubshapeTypes.HasFlag(SubshapeTypes.Face) && detectedShape.ShapeType() == TopAbs_ShapeEnum.FACE)
                {
                    selectedSubshape = detectedShape;
                    selectedSubshapeType = SubshapeTypes.Face;
                }
                else if (_SubshapeTypes.HasFlag(SubshapeTypes.All))
                {
                    selectedSubshape = detectedShape;
                    selectedSubshapeType = SubshapeTypes.All;
                }
            }

            return new EventArgs()
            {
                SelectedSubshape = selectedSubshape,
                SelectedSubshapeType = selectedSubshapeType,
                SelectedAisObject = selectedAisObject,
                SelectedEntity = selectedEntity,
                MouseEventData = data
            };
        }
        void _ProcessMouseSelect(MouseEventData data)
        {
            foreach (var detectedShape in data.DetectedShapes)
            {
             //   var subshape = _Subshapes.FirstOrDefault(sh => sh.Shape.IsEqual(detectedShape));
                var subshape = _Subshapes.FirstOrDefault(sh => sh.Shape.IsEqual(detectedShape));
                if (subshape != null)
                {
                    subshape.IsSelected = !subshape.IsSelected;
                    subshape.AisShape.SetColor((subshape.IsSelected ? Colors.FilteredSubshapesHot : Colors.FilteredSubshapes).ToQuantityColor());
                    //var dd = ShapeTools.Create((TopoDS_Edge)subshape.Shape ); 
                    //var start=dd.StartPoint;
                    EventArgs args = new()
                    {
                        SelectedSubshape = subshape.Shape,
                        SelectedAisObject = subshape.AisShape,
                        MouseEventData = data,
                        IsDo = true
                    };
                    Finished?.Invoke(this, args);
                    data.ForceReDetection = true;
                    break;
                }
            }
        }
        //--------------------------------------------------------------------------------------------------

        public override bool OnMouseMove(MouseEventData data)
        {
            if (!IsFinished)
            {
                EventArgs args = ProcessMouseInput(data);
                Preview?.Invoke(this, args);
                return base.OnMouseMove(data);
            }
            return false;
        }

        //--------------------------------------------------------------------------------------------------

        public override bool OnMouseUp(MouseEventData data)
        {
            
            if (!IsFinished && !SelectOnMouseDown)
            {
                
                EventArgs args = ProcessMouseInput(data);
                if (args.SelectedEntity != null || args.SelectedSubshape != null || args.SelectedAisObject != null)
                {
                
                    _ProcessMouseSelect(data);
                    Finished?.Invoke(this, args);
                  
                  
                }
            }
            return true;
        }

        //--------------------------------------------------------------------------------------------------

        public override bool OnMouseDown(MouseEventData data)
        {
            if (!IsFinished && SelectOnMouseDown)
            {
                EventArgs args = ProcessMouseInput(data);
                if (args.SelectedEntity != null || args.SelectedSubshape != null || args.SelectedAisObject != null)
                { 
                    Finished?.Invoke(this, args);
                }
            }
            return true;
        }

        //--------------------------------------------------------------------------------------------------

    }
}